package com.xnyzc.lhy.mis.service.impl.approval;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.component.sms.SubMailUtil;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.constant.SmsConstant;
import com.xnyzc.lhy.common.entity.Qd;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.EOrderType;
import com.xnyzc.lhy.common.penum.approval.EApprovalOrderStatus;
import com.xnyzc.lhy.common.penum.approval.EApprovalTaskStatus;
import com.xnyzc.lhy.common.penum.approval.EApproverType;
import com.xnyzc.lhy.common.penum.push.EAppPushContent;
import com.xnyzc.lhy.common.penum.push.EJPushConfigKey;
import com.xnyzc.lhy.common.penum.push.EPushCode;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.mis.entity.approval.OaApprovalTask;
import com.xnyzc.lhy.mis.entity.approval.OaApprovalTempChild;
import com.xnyzc.lhy.mis.entity.approval.OaApprovalTempPrimary;
import com.xnyzc.lhy.mis.entity.order.OaCOrderApprovalOfficial;
import com.xnyzc.lhy.mis.entity.param.approval.ApprovalOperationParam;
import com.xnyzc.lhy.mis.entity.result.user.UserLoginResult;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.mis.entity.system.OaSysUserRole;
import com.xnyzc.lhy.mis.entity.user.OaCUser;
import com.xnyzc.lhy.mis.feign.FeignMessageSendService;
import com.xnyzc.lhy.mis.mapper.approval.OaApprovalTaskMapper;
import com.xnyzc.lhy.mis.mapper.approval.OaApprovalTempChildMapper;
import com.xnyzc.lhy.mis.mapper.approval.OaApprovalTempPrimaryMapper;
import com.xnyzc.lhy.mis.mapper.approval.OaCRaiseApplyMapper;
import com.xnyzc.lhy.mis.mapper.order.OaCOrderApprovalOfficialMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.mis.mapper.system.OaSysUserRoleMapper;
import com.xnyzc.lhy.mis.mapper.user.OaCUserMapper;
import com.xnyzc.lhy.mis.service.approval.IOaApprovalTaskService;
import com.xnyzc.lhy.resource.entity.jpush.BizResult;
import com.xnyzc.lhy.resource.entity.jpush.PushInfoEntity;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 审批任务表 服务实现类
 * </p>
 *
 * @author huxuekuo
 * @since 2019-08-07
 */
@Slf4j
@Service
public class OaApprovalTaskServiceImpl extends ServiceImpl<OaApprovalTaskMapper, OaApprovalTask> implements IOaApprovalTaskService {

    @Autowired
    private OaApprovalTaskMapper oaApprovalTaskMapper;

    @Autowired
    OaApprovalTempPrimaryMapper oaApprovalTempPrimaryMapper;

    @Autowired
    OaApprovalTempChildMapper oaApprovalTempChildMapper;

    @Autowired
    OaSysUserRoleMapper oaSysUserRoleMapper;

    @Autowired
    OaSysOfficeMapper oaSysOfficeMapper;

    @Autowired
    OaCUserMapper oaCUserMapper;

    @Autowired
    IOaApprovalTaskService iOaApprovalTaskService;

    @Autowired
    OaCOrderApprovalOfficialMapper oaCOrderApprovalOfficialMapper;

    @Autowired
    OaCRaiseApplyMapper oaCRaiseApplyMapper;

    @Autowired
    OaCUserOfficeMapper oaCUserOfficeMapper;

    @Autowired
    RedisCommon redisCommon;

    /**
     * 极光推送
     */
    @Autowired
    private FeignMessageSendService feignMessageSendService;

    /**
     * 提交申请单，初始化审批任务
     *
     * @param userId
     * @param orderNo
     * @return
     */
    @Override
    public void initApprovalTask(Long userId, String orderNo, Integer applyMatter) {

        // 获取用户部门ID
        UserLoginResult userLoginResult = (UserLoginResult) TokenUtil.getTokenUserEntity(UserLoginResult.class);

        Long officeId = userLoginResult.getOfficeId();

        if (CheckUtil.objIsEmpty(officeId)) {
            oaCOrderApprovalOfficialMapper.delete(Qw.create().eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo));
            redisCommon.remove(RedisPrefixConstant.ORDER_OA_D_ORDER + orderNo);
            throw new PangException(EErrorCode.unOffice);
        }

        // 根据部门ID查询审批流主表信息
        OaApprovalTempPrimary oaApprovalTempPrimary = getApprovalTempInfo(officeId, applyMatter);
        // 获取审批节点
        OaApprovalTempChild oaApprovalTempChild = getOaApprovalTempChild(oaApprovalTempPrimary.getApprovalId());

        // 下发审批任务
        // 审批人类型
        Integer approverType = oaApprovalTempChild.getApproverType();
        // 审批人ID
        String approverIdStr = oaApprovalTempChild.getApproverId();
        // 是否并行审批（0：否、1：是）
        Integer isParallel = oaApprovalTempChild.getIsParallel();

        // 根据审批人类型查询审批人信息
        List<OaApprovalTask> oaApprovalTaskList = getOaApprovalTaskInfo(approverType, approverIdStr, userId, orderNo,
                officeId, oaApprovalTempChild);
        // 批量插入审批任务表
        iOaApprovalTaskService.saveBatch(oaApprovalTaskList);

        // 判断审批人是否是申请人
        // 发送短信给审批人
        List<Long> approvalUserIdList = new ArrayList<>();
        for (OaApprovalTask oat : oaApprovalTaskList) {
            if (Objects.equals(oat.getApprovalUserId(), userId)) {
                // 进入判断是否是最后一个审批节点方法
                List<Long> userIds = new ArrayList<>();
                userIds.add(userId);
                isEndApprovalNode(userIds, userId, officeId, isParallel, oaApprovalTempChild, oaApprovalTaskList, orderNo, "", 1);
                break;
            } else {
                approvalUserIdList.add(oat.getApprovalUserId());
                // 短信通知审批人
                messageSendApprover(userLoginResult, approvalUserIdList, orderNo);
            }
        }
    }

    /**
     * 判断是否是最后一个审批节点
     *
     * @param approvalUserIds     审批人userId
     * @param applyUserId         申请userId
     * @param isParallel          申请人部门ID
     * @param isParallel          是否并行
     * @param oaApprovalTempChild 当前节点
     * @param oaApprovalTaskList  当前节点的任务信息
     * @param orderNo             订单号
     * @param currentNode         当前节点
     * @return
     */
    private void isEndApprovalNode(List<Long> approvalUserIds, Long applyUserId, Long officeId, Integer isParallel, OaApprovalTempChild oaApprovalTempChild,
                                   List<OaApprovalTask> oaApprovalTaskList, String orderNo, String approvalOpinion, Integer currentNode) {

        // 查询审批节点
        List<OaApprovalTempChild> oaApprovalTempChildList = getOaApprovalTempChildList(oaApprovalTempChild);
        // 是否最后一个节点
        if (oaApprovalTempChildList.size() == 0) {
            // 是否并行审批
            if (Objects.equals(isParallel, 1)) {
                // 更新申请人审批任务表、申请表，并发送短信
                getApprovalTaskOperate(approvalUserIds, orderNo, oaApprovalTaskList, approvalOpinion);
                return;
            } else {
                // 判断除申请人其他人是否已审批完
                boolean approvalAllStatus = getApprovalAllStatus(approvalUserIds, oaApprovalTaskList);
                if (approvalAllStatus) {
                    // 更新申请人审批任务表、申请表，并发送短信
                    getApprovalTaskOperate(approvalUserIds, orderNo, oaApprovalTaskList, approvalOpinion);
                    return;
                } else {
                    // 更新任务表
                    updateApprovalTask(approvalUserIds, orderNo, EApprovalTaskStatus.pass.getValue(), approvalOpinion);
                    // 给其他审批人发送短信
                    sendApprovalUserSms(approvalUserIds, oaApprovalTaskList, orderNo);
                }
            }
        }
        // 不是最后一个节点
        else {
            // 判断是否是并行审批
            if (Objects.equals(isParallel, 1)) {
                // 更新审批任务表为审批通过
                updateApprovalTask(approvalUserIds, orderNo, EApprovalTaskStatus.pass.getValue(), approvalOpinion);
                // 更新订单节点
                updateApplyOrderNode(approvalUserIds, orderNo, oaApprovalTempChild);
                // 下一节点派发及处理
                dealNextNodeInfo(applyUserId, officeId, orderNo, oaApprovalTempChildList, currentNode + 1);

            }
            // 不是并行审批
            else {
                // 判断除申请人其他人是否已审批完
                boolean approvalAllStatus = getApprovalAllStatus(approvalUserIds, oaApprovalTaskList);
                if (approvalAllStatus) {
                    // 更新当前节点审批通过
                    updateCurrectNodePass(approvalUserIds, orderNo, currentNode, approvalOpinion);
                    // 更新订单节点
                    updateApplyOrderNode(approvalUserIds, orderNo, oaApprovalTempChild);
                    // 下一节点派发及处理
                    dealNextNodeInfo(applyUserId, officeId, orderNo, oaApprovalTempChildList, currentNode + 1);
                } else {
                    // 更新申请人的任务
                    updateApprovalTask(approvalUserIds, orderNo, EApprovalTaskStatus.pass.getValue(), approvalOpinion);
                    // 给其他审批人发送短信
                    sendApprovalUserSms(approvalUserIds, oaApprovalTaskList, orderNo);
                }
            }
        }
    }

    /**
     * 更新申请表的节点
     *
     * @param approvalUserIds
     * @param orderNo
     * @param oaApprovalTempChild
     */
    private void updateApplyOrderNode(List<Long> approvalUserIds, String orderNo, OaApprovalTempChild oaApprovalTempChild) {
        Date date = new Date();
        Long userId = TokenUtil.getTokenUserId();
        // 审批公务
        if (orderNo.contains(EOrderType.SPGW.getValue())) {
            OaCOrderApprovalOfficial oao = new OaCOrderApprovalOfficial();
            oao.setApprovalNode(oaApprovalTempChild.getApprovalNode() + 1);
            oao.setUpdateUser(userId);
            oao.setUpdateTime(date);
            UpdateWrapper<OaCOrderApprovalOfficial> oaCOrderApprovalOfficialUpdateWrapper = new UpdateWrapper<>();
            oaCOrderApprovalOfficialUpdateWrapper.eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo);
            oaCOrderApprovalOfficialMapper.update(oao, oaCOrderApprovalOfficialUpdateWrapper);
        }
    }

    /**
     * 更新审批任务表当前节点审批通过
     *
     * @param approvalUserIds
     * @param orderNo
     * @param currentNode
     * @param approvalOpinion
     */
    private void updateCurrectNodePass(List<Long> approvalUserIds, String orderNo, Integer currentNode, String approvalOpinion) {

        for (Long approvalUserId : approvalUserIds) {
            UpdateWrapper<OaApprovalTask> oaApprovalTaskUpdateWrapper = new UpdateWrapper<>();
            oaApprovalTaskUpdateWrapper.eq(OaApprovalTask.APPROVAL_NODE, currentNode)
                    .eq(OaApprovalTask.ORDER_NO, orderNo)
                    .eq(OaApprovalTask.APPROVAL_USER_ID, approvalUserId);
            // 更新
            OaApprovalTask oaApprovalTask = new OaApprovalTask();
            oaApprovalTask.setApprovalStatus(EApprovalTaskStatus.pass.getValue());
            oaApprovalTask.setApprovalOpinion(approvalOpinion);
            oaApprovalTask.setUpdateTime(new Date());
            oaApprovalTask.setUpdateUser(approvalUserId);
            oaApprovalTaskMapper.update(oaApprovalTask, oaApprovalTaskUpdateWrapper);
        }
    }

    /**
     * 下一节点派发及处理
     *
     * @param officeId
     * @param orderNo
     * @param oaApprovalTempChildList
     */
    private void dealNextNodeInfo(Long applyUserId, Long officeId, String orderNo, List<OaApprovalTempChild> oaApprovalTempChildList, Integer currentNode) {
        // 查询下一节点信息
        OaApprovalTempChild oaApprovalTempChildNext = oaApprovalTempChildList.get(0);
        // 根据审批人类型查询审批人信息
        List<OaApprovalTask> oaApprovalTaskNextList = getOaApprovalTaskInfo(oaApprovalTempChildNext.getApproverType(),
                oaApprovalTempChildNext.getApproverId(), applyUserId, orderNo, officeId, oaApprovalTempChildNext);
        // 批量插入审批任务表
        iOaApprovalTaskService.saveBatch(oaApprovalTaskNextList);

        // 获取当前节点之前的审批任务信息
        List<OaApprovalTask> beforeOaApprovalTaskList = getBeforeOaApprovalTaskList(oaApprovalTempChildNext.getApprovalNode(), orderNo);
        boolean isApproverUser = false;
        // 判断当前审批节点审批人是否是申请人，及 判断审批人是否已审批过
        boolean isApprovalApplyUser = false;
        // 下一节点已审批过的人
        List<Long> nextApprovalUserIds = new ArrayList<>();

        // 审批人userId
        List<Long> approvalUserIds = new ArrayList<>();
        for (OaApprovalTask t : oaApprovalTaskNextList) {
            if (Objects.equals(t.getApprovalUserId(), applyUserId)) {
                isApprovalApplyUser = true;
                nextApprovalUserIds.add(t.getApprovalUserId());
            } else {
                approvalUserIds.add(t.getApprovalUserId());
            }
            for (OaApprovalTask o : beforeOaApprovalTaskList) {
                if (Objects.equals(o.getApprovalUserId(), t.getApprovalUserId()) && Objects.equals(o.getApprovalStatus(), EApprovalTaskStatus.pass.getValue())) {
                    isApproverUser = true;
                    nextApprovalUserIds.add(o.getApprovalUserId());
                }
            }
        }
        if (isApprovalApplyUser || isApproverUser) {
            isEndApprovalNode(nextApprovalUserIds, applyUserId, officeId, oaApprovalTempChildNext.getIsParallel(), oaApprovalTempChildNext, oaApprovalTaskNextList, orderNo, "", currentNode);
        } else {
            if (!CheckUtil.objIsEmpty(approvalUserIds)) {
                // 短信通知审批人
                List<OaCUser> oaCUserList = oaCUserMapper.selectBatchIds(approvalUserIds);
                List<String> approvalPhones = new ArrayList<>();
                for (OaCUser o : oaCUserList) {
                    approvalPhones.add(o.getUserPhone());
                }
                approvalNotifySend(approvalPhones);
            }
        }
    }

    /**
     * 获取当前节点之前的审批任务信息
     *
     * @param approvalNode
     * @param orderNo
     * @return
     */
    private List<OaApprovalTask> getBeforeOaApprovalTaskList(Integer approvalNode, String orderNo) {

        QueryWrapper<OaApprovalTask> oaApprovalTaskQueryWrapper = new QueryWrapper<>();
        oaApprovalTaskQueryWrapper.eq(OaApprovalTask.ORDER_NO, orderNo);
        oaApprovalTaskQueryWrapper.lt(OaApprovalTask.APPROVAL_NODE, approvalNode);
        List<OaApprovalTask> oaApprovalTasks = oaApprovalTaskMapper.selectList(oaApprovalTaskQueryWrapper);
        return oaApprovalTasks;
    }

    private void sendApprovalUserSms(List<Long> applyUserIds, List<OaApprovalTask> oaApprovalTaskList, String orderNo) {
        List<Long> approvalUserIds = new ArrayList<>();
        for (Long applyUserId : applyUserIds) {
            for (OaApprovalTask oat : oaApprovalTaskList) {
                if (!Objects.equals(applyUserId, oat.getApplyUserId())) {
                    approvalUserIds.add(oat.getApprovalUserId());
                }
            }
        }
        if (!CheckUtil.objIsEmpty(approvalUserIds)) {
            // 查询审批人手机号
            List<OaCUser> oaCUsers = oaCUserMapper.selectBatchIds(approvalUserIds);
            sendSmsApprover(oaCUsers, orderNo);
        }
    }

    /**
     * 更新所有审批人的任务表
     *
     * @param orderNo
     * @return
     */
    private void getApprovalTaskOperate(List<Long> approvalUserIds, String orderNo, List<OaApprovalTask> oaApprovalTaskList, String approvalOpinion) {
        // 更新审批任务表
        updateApprovalTask(approvalUserIds, orderNo, EApprovalTaskStatus.pass.getValue(), approvalOpinion);
        // 更新订单申请表
        updateApplyOrder(orderNo, EApprovalOrderStatus.pass.getValue());
        // 发送短信
        String phone = getCPhone(oaApprovalTaskList.get(0).getApplyUserId());
        try {
            JSONObject jsonObject = new JSONObject();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jsonObject.put("time", sdf.format(new Date()));
            SubMailUtil.messageMultiSend(phone, SmsConstant.APPROVAL_PASS, jsonObject);
            // 极光推送
            List<String> phones = new ArrayList<>();
            phones.add(phone);
            this.push(phones, orderNo, 0, EAppPushContent.approvalPass.getDesc());
        } catch (Exception e) {
        }
    }

    /**
     * 判断除申请人其他人是否已审批完
     *
     * @param approvalUserIds
     * @param oaApprovalTaskList
     * @return
     */
    private boolean getApprovalAllStatus(List<Long> approvalUserIds, List<OaApprovalTask> oaApprovalTaskList) {
        boolean approvalAllStatus = true;
        int approvalNum = 0;
        if (oaApprovalTaskList.size() > 1) {
            for (OaApprovalTask oat : oaApprovalTaskList) {
                if (Objects.equals(oat.getApprovalStatus(), EApprovalTaskStatus.pending.getValue())) {
                    approvalNum++;
                }
            }
            if (approvalNum > approvalUserIds.size()) {
                approvalAllStatus = false;
            }
        }

        return approvalAllStatus;
    }

    /**
     * 更新订单申请表
     *
     * @param orderNo
     * @param status
     */
    private void updateApplyOrder(String orderNo, Integer status) {

        Date date = new Date();
        // 审批公务
        if (orderNo.contains(EOrderType.SPGW.getValue())) {
            OaCOrderApprovalOfficial oao = new OaCOrderApprovalOfficial();
            oao.setApprovalStatus(status);
            oao.setUpdateTime(date);
            UpdateWrapper<OaCOrderApprovalOfficial> oaCOrderApprovalOfficialUpdateWrapper = new UpdateWrapper<>();
            oaCOrderApprovalOfficialUpdateWrapper.eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo);

            oaCOrderApprovalOfficialMapper.update(oao, oaCOrderApprovalOfficialUpdateWrapper);
        }
    }

    /**
     * 获取手机号
     *
     * @param applyUserId
     * @return
     */
    private String getCPhone(Long applyUserId) {
        OaCUser oaCUser = oaCUserMapper.selectById(applyUserId);
        String phone = oaCUser.getUserPhone();

        return phone;

    }

    /**
     * 更新审批任务表
     *
     * @param approvalUserIds
     * @param orderNo
     * @param value
     * @param approvalOpinion
     */
    private void updateApprovalTask(List<Long> approvalUserIds, String orderNo, Integer value, String approvalOpinion) {
        Date date = new Date();
        for (Long approvalUserId : approvalUserIds) {
            OaApprovalTask oaApprovalTask = new OaApprovalTask();
            oaApprovalTask.setApprovalStatus(value);
            oaApprovalTask.setApprovalOpinion(approvalOpinion);
            oaApprovalTask.setUpdateTime(date);
            oaApprovalTask.setUpdateUser(approvalUserId);
            UpdateWrapper<OaApprovalTask> oaApprovalTaskUpdateWrapper = new UpdateWrapper<>();
            oaApprovalTaskUpdateWrapper.eq(OaApprovalTask.ORDER_NO, orderNo);
            oaApprovalTaskUpdateWrapper.eq(OaApprovalTask.APPROVAL_USER_ID, approvalUserId);
            oaApprovalTaskMapper.update(oaApprovalTask, oaApprovalTaskUpdateWrapper);
        }
    }


    /**
     * 根据审批流ID查询审批节点
     *
     * @param oaApprovalTempChild
     * @return
     */
    private List<OaApprovalTempChild> getOaApprovalTempChildList(OaApprovalTempChild oaApprovalTempChild) {
        QueryWrapper<OaApprovalTempChild> oaApprovalTempChildQueryWrapper = new QueryWrapper<>();
        oaApprovalTempChildQueryWrapper.eq(OaApprovalTempChild.APPROVAL_ID, oaApprovalTempChild.getApprovalId());
        oaApprovalTempChildQueryWrapper.gt(OaApprovalTempChild.APPROVAL_NODE, oaApprovalTempChild.getApprovalNode());
        oaApprovalTempChildQueryWrapper.orderByAsc(OaApprovalTempChild.APPROVAL_NODE);
        List<OaApprovalTempChild> oaApprovalTempChildList = oaApprovalTempChildMapper.selectList(oaApprovalTempChildQueryWrapper);
        return oaApprovalTempChildList;
    }

    /**
     * 根据审批人类型查询审批人信息
     *
     * @param approverType
     * @param approverIdStr
     * @param userId
     * @param orderNo
     * @param officeId
     * @param oaApprovalTempChild
     * @return
     */
    private List<OaApprovalTask> getOaApprovalTaskInfo(Integer approverType, String approverIdStr, Long userId,
                                                       String orderNo, Long officeId, OaApprovalTempChild oaApprovalTempChild) {

        Date date = new Date();
        List<OaApprovalTask> oaApprovalTaskList = new ArrayList<>();
        // 指定成员
        if (Objects.equals(approverType, EApproverType.designatedMember.getValue())) {
            String[] approverIdArray = approverIdStr.split(",");
            for (String approverId : approverIdArray) {
                OaApprovalTask oaApprovalTask = new OaApprovalTask();
                oaApprovalTask.setApprovalUserId(Long.valueOf(approverId));
                oaApprovalTaskList.add(oaApprovalTask);
            }
        }
        // 角色
        else if (Objects.equals(approverType, EApproverType.role)) {
            // 查询关联角色的人员(一个审批节点只可配置一个角色)
            QueryWrapper<OaSysUserRole> oaSysUserRoleQueryWrapper = new QueryWrapper<>();
            oaSysUserRoleQueryWrapper.eq(OaSysUserRole.ROLE_ID, approverIdStr.substring(0, approverIdStr.length() - 1));
            List<OaSysUserRole> oaSysUserRoleList = oaSysUserRoleMapper.selectList(oaSysUserRoleQueryWrapper);
            if (CheckUtil.objIsEmpty(oaSysUserRoleList)) {
                throw new PangException(EErrorCode.noApprovalNode);
            }
            for (OaSysUserRole oaSysUserRole : oaSysUserRoleList) {
                OaApprovalTask oaApprovalTask = new OaApprovalTask();
                oaApprovalTask.setApprovalUserId(Long.valueOf(oaSysUserRole.getUserId()));
                oaApprovalTaskList.add(oaApprovalTask);
            }
        }
        // 主管
        else if (Objects.equals(approverType, EApproverType.supervisor.getValue())) {
            // 查询申请人部门主负责人
            OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(officeId);
            if (CheckUtil.objIsEmpty(oaSysOffice)) {
                throw new PangException(EErrorCode.noApprovalNode);
            }
            OaApprovalTask oaApprovalTask = new OaApprovalTask();
            oaApprovalTask.setApprovalUserId(Long.valueOf(oaSysOffice.getPrimaryPerson()));
            oaApprovalTaskList.add(oaApprovalTask);
        }
        // 发起人自己
        else if (Objects.equals(approverType, EApproverType.sponsor.getValue())) {
            OaApprovalTask oaApprovalTask = new OaApprovalTask();
            oaApprovalTask.setApprovalUserId(userId);
            oaApprovalTaskList.add(oaApprovalTask);
        }

        if (CheckUtil.objIsEmpty(oaApprovalTaskList)) {
            throw new PangException(EErrorCode.noApprovalNode);
        }
        String tag = TokenUtil.getTag();
        // set公共信息
        for (OaApprovalTask oat : oaApprovalTaskList) {
            Long id = IDUtil.nextId();
            oat.setTaskId(id);
            oat.setOrderNo(orderNo);
            oat.setApplyUserId(userId);
            oat.setCreateUser(id);
            oat.setCreateTime(date);
            oat.setTag(tag);
            oat.setUpdateUser(id);
            oat.setUpdateTime(date);
            oat.setApprovalNode(oaApprovalTempChild.getApprovalNode());
            oat.setApprovalStatus(EApprovalTaskStatus.pending.getValue());
        }

        return oaApprovalTaskList;
    }

    /**
     * 根据部门ID,审批事项查询审批主表信息
     *
     * @param officeId
     * @param applyMatter
     * @return
     */
    public OaApprovalTempPrimary getApprovalTempInfo(Long officeId, Integer applyMatter) {
        Map<String, Object> sqlMap = new HashMap<>(16);
        sqlMap.put("officeId", officeId);
        sqlMap.put("applyMatter", applyMatter);
        OaApprovalTempPrimary oaApprovalTempPrimary = oaApprovalTempPrimaryMapper.getApprovalTempInfo(sqlMap);
        if (CheckUtil.objIsEmpty(oaApprovalTempPrimary)) {
            throw new PangException(EErrorCode.noApproval);
        }
        return oaApprovalTempPrimary;
    }

    /**
     * 审批人进行审批操作
     *
     * @param approvalOperationParam
     * @return
     */
    @Override
    public Rv approvalOperation(ApprovalOperationParam approvalOperationParam) {

        // 申请订单号
        String orderNo = approvalOperationParam.getOrderNo();
        // 审批状态
        Integer approvalStatus = approvalOperationParam.getApprovalStatus();
        // 审批意见
        String approvalOpinion = approvalOperationParam.getApprovalOpinion();
        // 审批人
        Long approvalUserId = TokenUtil.getTokenUserId();

        Date date = new Date();

        // 获取订单信息
        Long applyUserId = 0L;
        Long officeId = 0L;
        // 审批流ID
        Long approvalId = 0L;
        // 当前审批节点
        Integer currentApprovalNode = -1;
        // 校验审批订单是否已经是完成状态
        this.checkAppOrderComplete(orderNo);
        // 审批公务
        if (orderNo.contains(EOrderType.SPGW.getValue())) {
            QueryWrapper<OaCOrderApprovalOfficial> oaCOrderApprovalOfficialQueryWrapper = new QueryWrapper<>();
            oaCOrderApprovalOfficialQueryWrapper.eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo);
            OaCOrderApprovalOfficial oaCOrderApprovalOfficial = oaCOrderApprovalOfficialMapper.selectOne(oaCOrderApprovalOfficialQueryWrapper);
            if (CheckUtil.objIsEmpty(oaCOrderApprovalOfficial)) {
                throw new PangException(EErrorCode.unData);
            }
            applyUserId = oaCOrderApprovalOfficial.getUserId();
            officeId = oaCOrderApprovalOfficial.getOfficeId();
            approvalId = oaCOrderApprovalOfficial.getApprovalId();
            currentApprovalNode = oaCOrderApprovalOfficial.getApprovalNode();
        }

        // 审批通过
        if (Objects.equals(approvalStatus, EApprovalTaskStatus.pass.getValue())) {
            // 根据审批流ID，当前节点查询审批流信息
            OaApprovalTempChild oaApprovalTempChild = getOaApprovalTempChildInfo(approvalId, currentApprovalNode);
            Integer isParallel = oaApprovalTempChild.getIsParallel();
            // 根据审批人类型查询当前审批节点信息
            List<OaApprovalTask> oaApprovalTaskList = getOaApprovalTaskCurrentInfo(orderNo, currentApprovalNode);
            List<Long> approvalUserIds = new ArrayList<>();
            approvalUserIds.add(approvalUserId);
            isEndApprovalNode(approvalUserIds, applyUserId, officeId, isParallel, oaApprovalTempChild, oaApprovalTaskList, orderNo, approvalOpinion, currentApprovalNode);
        }
        // 审批拒绝
        else {
            // 更新任务表
            QueryWrapper<OaApprovalTask> oaApprovalTaskQueryWrapper = new QueryWrapper<>();
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.ORDER_NO, orderNo);
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.APPROVAL_NODE, currentApprovalNode);
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.APPROVAL_STATUS, EApprovalTaskStatus.pending);
            OaApprovalTask oaApprovalTask = new OaApprovalTask();
            oaApprovalTask.setApprovalStatus(EApprovalTaskStatus.reject.getValue());
            oaApprovalTask.setApprovalOpinion(approvalOpinion);
            oaApprovalTask.setUpdateTime(date);
            oaApprovalTask.setUpdateUser(approvalUserId);
            oaApprovalTaskMapper.update(oaApprovalTask, oaApprovalTaskQueryWrapper);

            // 更新审批公务申请表
            if (orderNo.contains(EOrderType.SPGW.getValue())) {
                QueryWrapper<OaCOrderApprovalOfficial> oaCOrderApprovalOfficialQueryWrapper = new QueryWrapper<>();
                oaCOrderApprovalOfficialQueryWrapper.eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo);
                OaCOrderApprovalOfficial oaCOrderApprovalOfficial = new OaCOrderApprovalOfficial();
                oaCOrderApprovalOfficial.setApprovalStatus(EApprovalOrderStatus.reject.getValue());
                oaCOrderApprovalOfficial.setUpdateTime(date);
                oaCOrderApprovalOfficial.setUpdateUser(approvalUserId);
                oaCOrderApprovalOfficialMapper.update(oaCOrderApprovalOfficial, oaCOrderApprovalOfficialQueryWrapper);
            }

            // 短信通知申请人
            OaCUser oaCUser = oaCUserMapper.selectById(applyUserId);
            try {
                UserLoginResult userLoginResult = (UserLoginResult) TokenUtil.getTokenUserEntity(UserLoginResult.class);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", userLoginResult.getUserName());
                SubMailUtil.messageMultiSend(oaCUser.getUserPhone(), SmsConstant.APPROVAL_REFUSE, jsonObject);
                // 极光推送
                List<String> phones = new ArrayList<>();
                phones.add(oaCUser.getUserPhone());
                String content = String.format(EAppPushContent.approvalRefuse.getDesc(), userLoginResult.getUserName());
                this.push(phones, orderNo, 0, content);
            } catch (Exception e) {
            }
        }

        return Rv.wrap(EErrorCode.success, Qd.create());
    }

    /**
     * 根据审批人类型查询当前审批节点信息
     *
     * @param orderNo
     * @param currentApprovalNode
     * @return
     */
    private List<OaApprovalTask> getOaApprovalTaskCurrentInfo(String orderNo, Integer currentApprovalNode) {
        QueryWrapper<OaApprovalTask> oaApprovalTaskQueryWrapper = new QueryWrapper<>();
        oaApprovalTaskQueryWrapper.eq(OaApprovalTask.ORDER_NO, orderNo).eq(OaApprovalTask.APPROVAL_NODE, currentApprovalNode);

        List<OaApprovalTask> oaApprovalTaskList = oaApprovalTaskMapper.selectList(oaApprovalTaskQueryWrapper);
        if (CheckUtil.objIsEmpty(oaApprovalTaskList)) {
            throw new PangException(EErrorCode.approvalInfo);
        }
        return oaApprovalTaskList;
    }


    /**
     * 申请人取消申请或催审批
     *
     * @param orderNo
     * @param operationType 0:取消申请、1：催审批
     * @return
     */
    @Override
    public Rv applyUserOperation(String orderNo, Integer operationType) {
        // 校验审批订单是否完成
        this.checkAppOrderComplete(orderNo);
        // 获取订单信息
        if (orderNo.contains(EOrderType.SPGW.getValue())) {
            QueryWrapper<OaCOrderApprovalOfficial> oaCOrderApprovalOfficialQueryWrapper = new QueryWrapper<>();
            oaCOrderApprovalOfficialQueryWrapper.eq(OaCOrderApprovalOfficial.ORDER_NO, orderNo);
            OaCOrderApprovalOfficial oaCOrderApprovalOfficial = oaCOrderApprovalOfficialMapper.selectOne(oaCOrderApprovalOfficialQueryWrapper);

            // 获取审批信息
            QueryWrapper<OaApprovalTask> oaApprovalTaskQueryWrapper = new QueryWrapper<>();
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.ORDER_NO, oaCOrderApprovalOfficial.getOrderNo());
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.APPROVAL_NODE, oaCOrderApprovalOfficial.getApprovalNode());
            oaApprovalTaskQueryWrapper.eq(OaApprovalTask.APPROVAL_STATUS, EApprovalTaskStatus.pending);
            List<OaApprovalTask> oaApprovalTasks = oaApprovalTaskMapper.selectList(oaApprovalTaskQueryWrapper);

            if (CheckUtil.objIsEmpty(oaApprovalTasks)) {
                throw new PangException(EErrorCode.approvalInfo);
            }
            // 0:取消申请、1：催审批
            if (Objects.equals(operationType, 0)) {
                oaCOrderApprovalOfficial.setApprovalStatus(EApprovalOrderStatus.cancel.getValue());
                oaCOrderApprovalOfficialMapper.updateById(oaCOrderApprovalOfficial);

                List<Long> taskIds = new ArrayList<>();
                for (OaApprovalTask oat : oaApprovalTasks) {
                    taskIds.add(oat.getTaskId());
                }
                UpdateWrapper<OaApprovalTask> oaApprovalTaskUpdateWrapper = new UpdateWrapper<>();
                oaApprovalTaskUpdateWrapper.in(OaApprovalTask.TASK_ID, taskIds);
                OaApprovalTask oaApprovalTask = new OaApprovalTask();
                oaApprovalTask.setApprovalStatus(EApprovalTaskStatus.cancelApply.getValue());
                oaApprovalTask.setUpdateTime(new Date());
                oaApprovalTask.setUpdateUser(oaCOrderApprovalOfficial.getUserId());
                oaApprovalTaskMapper.update(oaApprovalTask, oaApprovalTaskUpdateWrapper);
            } else if (Objects.equals(operationType, 1)) {
                List<Long> approvalUserId = new ArrayList<>();
                for (OaApprovalTask oat : oaApprovalTasks) {
                    approvalUserId.add(oat.getApprovalUserId());
                }
                // 查询审批人手机号
                List<OaCUser> oaCUsers = oaCUserMapper.selectBatchIds(approvalUserId);
                if (!CheckUtil.objIsEmpty(oaCUsers)) {
                    List<String> phoneList = new ArrayList<>();
                    for (OaCUser o : oaCUsers) {
                        phoneList.add(o.getUserPhone());
                    }
                    UserLoginResult userLoginResult = (UserLoginResult) TokenUtil.getTokenUserEntity(UserLoginResult.class);
                    String userName = userLoginResult.getUserName();
                    // 批量发送短信
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("name", userName);
                    try {
                        SubMailUtil.messageMultiSends(phoneList, SmsConstant.URGE_APPROVAL, jsonObject);
                        // 极光推送
                        String content = String.format(EAppPushContent.urgeApproval.getDesc(), userName);
                        this.push(phoneList, orderNo, 1, content);
                    } catch (Exception e) {

                    }
                }
            }
        } else {
            throw new PangException(EErrorCode.unOrderNo);
        }

        return Rv.wrap(EErrorCode.success, Qd.create());
    }

    /**
     * 根据审批流ID，当前节点查询审批流信息
     *
     * @param approvalId
     * @param currentApprovalNode
     * @return
     */
    private OaApprovalTempChild getOaApprovalTempChildInfo(Long approvalId, Integer currentApprovalNode) {

        QueryWrapper<OaApprovalTempChild> oaApprovalTempChildQueryWrapper = new QueryWrapper<>();
        oaApprovalTempChildQueryWrapper.eq(OaApprovalTempChild.APPROVAL_ID, approvalId)
                .eq(OaApprovalTempChild.APPROVAL_NODE, currentApprovalNode);

        OaApprovalTempChild oaApprovalTempChild = oaApprovalTempChildMapper.selectOne(oaApprovalTempChildQueryWrapper);
        return oaApprovalTempChild;

    }

    /**
     * 根据审批人ID查询手机号并发送短信
     *
     * @param userLoginResult
     * @param approvalUserIdList
     */
    private void messageSendApprover(UserLoginResult userLoginResult, List<Long> approvalUserIdList, String orderNo) {
        QueryWrapper<OaCUser> oaCUserQueryWrapper = new QueryWrapper<>();
        oaCUserQueryWrapper.select(OaCUser.USER_PHONE).in(OaCUser.USER_ID, approvalUserIdList);
        List<OaCUser> oaCUserList = oaCUserMapper.selectList(oaCUserQueryWrapper);
        sendSmsApprover(oaCUserList, orderNo);
    }

    /**
     * 发送短信给审批人
     *
     * @param oaCUserList
     */
    private void sendSmsApprover(List<OaCUser> oaCUserList, String orderNo) {
        if (!CheckUtil.objIsEmpty(oaCUserList)) {
            List<String> phoneList = new ArrayList<>();
            for (OaCUser oaCUser : oaCUserList) {
                phoneList.add(oaCUser.getUserPhone());
            }
            // 批量发送短信
            approvalNotifySend(phoneList);
            // 极光推送
            this.push(phoneList, orderNo, 1, EAppPushContent.approvalNotify.getDesc());
        }
    }

    /**
     * 批量发送短信
     * @param phoneList
     */
    private void approvalNotifySend(List<String> phoneList) {
        try {
            JSONObject jsonObject = new JSONObject();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            jsonObject.put("time", sdf.format(new Date()));
            SubMailUtil.messageMultiSends(phoneList, SmsConstant.APPROVAL_NOTIFY, jsonObject);
        } catch (Exception e) {
        }
    }

    /**
     * 根据审批流ID查询审批模板字表节点
     *
     * @param approvalId
     * @return
     */
    private OaApprovalTempChild getOaApprovalTempChild(Long approvalId) {
        QueryWrapper<OaApprovalTempChild> oaApprovalTempChildQueryWrapper = new QueryWrapper<>();
        oaApprovalTempChildQueryWrapper.eq(OaApprovalTempChild.APPROVAL_ID, approvalId);
        oaApprovalTempChildQueryWrapper.eq(OaApprovalTempChild.APPROVAL_NODE, 1);
        OaApprovalTempChild oaApprovalTempChild = oaApprovalTempChildMapper.selectOne(oaApprovalTempChildQueryWrapper);
        if (CheckUtil.objIsEmpty(oaApprovalTempChild)) {
            throw new PangException(EErrorCode.noApprovalNode);
        }
        return oaApprovalTempChild;
    }

    /**
     * 极光推送 审批
     */
    private void push(List<String> phones, String orderNo, Integer type, String content){
        com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
        com.alibaba.fastjson.JSONObject expand = new com.alibaba.fastjson.JSONObject();
        expand.put("orderNo", orderNo);
        expand.put("type", type);
        jsonObject.put("expand", JSON.toJSONString(expand));
        PushInfoEntity pushInfoEntity = new PushInfoEntity();
        // 我的申请
        if (type.equals(0)){
            pushInfoEntity.setPushCode(EPushCode.apply.getValue());
        }
        // 我的审核
        else {
            pushInfoEntity.setPushCode(EPushCode.approver.getValue());
        }
        pushInfoEntity.setPhones(phones);
        pushInfoEntity.setExtras(jsonObject);
        pushInfoEntity.setContent(content);
        pushInfoEntity.setTag(TokenUtil.getTag());
        pushInfoEntity.setClientId(EJPushConfigKey.passenger.getValue());
        BizResult bizResult = feignMessageSendService.pushMessage(pushInfoEntity);

        log.info("{}", bizResult.toString());

        if (bizResult.getCode() == 1) {
            log.info("推送成功");
        } else {
            log.info("推送失败");
        }
    }

    /**
     * 校验审批订单是否完成
     * @param orderNo 订单号
     */
    private void checkAppOrderComplete(String orderNo){
        String tag = TokenUtil.getTag();
        List<OaCOrderApprovalOfficial> oaCOrderApprovalOfficials = oaCOrderApprovalOfficialMapper.selectList(
                Wrappers.<OaCOrderApprovalOfficial>lambdaQuery()
                        .eq(OaCOrderApprovalOfficial::getTag, tag)
                        .eq(OaCOrderApprovalOfficial::getOrderNo, orderNo));
        if (oaCOrderApprovalOfficials.size() != 1){
            log.info("用户来源 %s ,查询 %s 条审批订单,订单号 %s", tag, oaCOrderApprovalOfficials.size(), orderNo);
            throw PangException.create(EErrorCode.approvalInfo);
        }
        OaCOrderApprovalOfficial approvalOfficial = oaCOrderApprovalOfficials.get(0);
        Integer officialApprovalStatus = approvalOfficial.getApprovalStatus();
        if (EApprovalOrderStatus.pass.getValue().equals(officialApprovalStatus) ||
                EApprovalOrderStatus.reject.getValue().equals(officialApprovalStatus) ||
                EApprovalOrderStatus.cancel.getValue().equals(officialApprovalStatus)){
            throw PangException.create(EErrorCode.approvalComplete);
        }
    }
}
